package com.kitty.game.rank.service.handler;

import com.kitty.common.utils.SpringUtils;
import com.kitty.game.rank.model.record.RankRecord;
import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentSkipListMap;

/**分段排行榜*/
public abstract class RangeRankHandler {
    /**
     * 用于快速查找 id --> record
     */
    private ConcurrentMap<Serializable, ConcurrentMap<Serializable, RankRecord>> cache = new ConcurrentHashMap<>();

    private ConcurrentMap<Serializable, ConcurrentSkipListMap<RankRecord, Serializable>> ranks = new ConcurrentHashMap<>();

    @Getter
    @Setter
    private int rankSize = 100;
    /**
     * 缓存数量要比排行榜数量大，防止战力下降，没有数据补充
     */
    @Setter
    private int cacheSize = rankSize + 50;

    /**
     * 读取数据库进行初始化
     */
    protected abstract void  init();

    protected boolean put(Serializable range, Serializable key, RankRecord data) {
        ConcurrentMap<Serializable, RankRecord> cacheMap = cache.get(range);
        if (cacheMap == null) {
            cacheMap = cache.putIfAbsent(range, new ConcurrentHashMap<>());
            if (cacheMap == null) {
                cacheMap = cache.get(range);
            }
        }
        cacheMap.put(key, data);

        ConcurrentSkipListMap<RankRecord, Serializable> ranksMap = ranks.get(range);
        if (ranksMap == null) {
            ranksMap = ranks.putIfAbsent(range, new ConcurrentSkipListMap<>());
            if (ranksMap == null) {
                ranksMap = ranks.get(range);
            }
        }
        ranksMap.put(data, key);
        if (ranksMap.size() > cacheSize) {
            Map.Entry<RankRecord, Serializable> lastEntry = ranksMap.pollLastEntry();
            remove(range, lastEntry.getValue());

            if (lastEntry.getValue() != key) {
                SpringUtils.getRankService().removeRandView(String.valueOf(lastEntry.getValue()));
                return true;
            }

            return false;
        }
        return true;
    }

    protected RankRecord remove(Serializable range, Serializable key) {
        ConcurrentMap<Serializable, RankRecord> cacheMap = cache.get(range);
        if (cacheMap == null) {return null;}
        RankRecord value = cacheMap.remove(key);
        if (value == null) {return null;}

        ConcurrentSkipListMap<RankRecord, Serializable> ranksMap = ranks.get(range);
        if (ranksMap == null) {return null;}
        Serializable removeKey = ranksMap.remove(value);
        if (removeKey != null) {
            return value;
        }

        return null;
    }

    /**
     * 由外部接受事件进行数据更新
     * @param key
     * @param data
     */
    public boolean update(Serializable range, Serializable key, RankRecord data) {
        remove(range, key);
        return put(range, key, data);
    }

    public List<RankRecord> getRecordsFrom(Serializable range, int start, int end) {
        List<RankRecord> result = new ArrayList<>();

        int i =0;
        ConcurrentSkipListMap<RankRecord, Serializable> ranksMap = ranks.get(range);
        if (ranksMap != null) {
            for (Iterator<Map.Entry<RankRecord, Serializable>> it = ranksMap.entrySet().iterator(); it.hasNext();) {
                Map.Entry<RankRecord, Serializable> next = it.next();
                if (i++ < end) {
                    result.add(next.getKey());
                }
            }
        }

        return result;
    }

    /**重置排行榜*/
    public void resetRank(Serializable range) {
        cache.remove(range);
        ranks.remove(range);
    }
}
